/**
 * @class   wosh::NetworkManager
 * @brief   CoreModule designed to manage host-discovery, networking and routing of wosh::Message.
 *
 *
 * \image html diagrams/NetworkManager.png "wosh::NetworkManager UML diagram"
 *
 *
 *
 * \par Initialization:
 * \msc
NetworkManager;
NetworkManager->NetworkManager [label="WoshModule::onKernelInitializing()", URL="\ref wosh::WoshModule::onKernelInitializing()"];
|||;
NetworkManager<=NetworkManager [ label="asynch start NetworkOutMessageHandler thread", URL="\ref wosh::NetworkOutMessageHandler"];
NetworkManager<=NetworkManager [ label="asynch start NetworkInMessageHandler thread", URL="\ref wosh::NetworkInMessageHandler"];
NetworkManager<=NetworkManager [ label="asynch start NetworkManagerLooper thread", URL="\ref wosh::NetworkManagerLooper"];
|||;
--- [ label=" IF AutoLoadProtocols "];
NetworkManager rbox NetworkManager [ label="install NetworkProtocol(s)"];
--- [ label=" ENDIF AutoLoadProtocols "];
--- [ label=" IF ListenChannels "];
NetworkManager rbox NetworkManager [ label="listen NetworkChannel(s)", URL="\ref wosh::NetworkManager::createChannel()"];
--- [ label=" ENDIF ListenChannels "];
 * \endmsc
 *
 *
 *
 *
 * Relations:
 *
 * Setup:
 * - Channels and/or ChannelLoader are installed
 * - Hosts are added/updated/removed (subscribed)
 *
 *
 * NetworkManager -> IBusListener
 * BusManager will register NetworkManager-Handler to busses.
 * ...
 *
 * @par Flows:
 *
 *  Outgoing Discovery:
 *    When new channels are available, localhost's protocols are updated (added).
 *    Moreover a (local-kernel) Fact is raised (notifiying the new channel)
 *
 * @see NetworkManager::installChannel()
 *
 *
 *  Incoming Discovery:
 *    When an Host is found (or updated), 
 *
 * @see NetworkManager::_updateWoshHost()
 *
 *
 * @see     wosh::NetworkProtocol
 * @see     wosh::NetworkChannel
 * @ingroup CoreModules
 ****************************************************************************
 * @version 0.6.030 $Id: NetworkManager.h 2827 2010-08-02 11:01:48Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/*! \page page_core
 * \htmlonly <hr/> \endhtmlonly
 * \section page_core_network Network
 *
 * [..]
 *
 * WOSH provides an high abstraction layer of networking communication, also
 * called network overlay.
 *
 * Within a single WOSH host, services exchange information through messages
 * (wosh::Message) over busses (wosh::Bus), as you have seen in \ref page_core_busses.
 *
 * Connecting multiple WOSH hosts means, basically, connected their busses,
 * manage routing and connection resilience.
 * The wosh::NetworkManager core module accomplishes these tasks.
 *
 *
 *
 * 
 * \code
// install NetworkProtocol loader (built-in protocols)
core.network().installNetworkProtocolAllocator( new NetworkProtocolAllocatorStatic() );
 * \endcode
 *
 * \see wosh::NetworkManager
 * \see wosh::NetworkProtocol
 * \see wosh::NetworkChannel
 *
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR UserS;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_NetworkManager_H__
 #define __WOSH_Core_NetworkManager_H__

 #include <woshDefs.h>
 #include <core/WoshModule.h>
 #include <core/Containers.h>
 #include <core/WoshHost.h>
 #include <core/NetworkChannel.h>
 #include <core/NetworkProtocol.h>


namespace wosh {

 #define _NetworkManager_NAME							"NetworkManager"
 #define _NetworkManager_URI							":Network"

 #define _NetworkManager_KEY_Hosts_Count				"HostCount"
 #define _NetworkManager_KEY_Channels_Count				"ChannelsCount"
 #define _NetworkManager_KEY_Protocols_Count			"ProtocolCount"

 #define _NetworkManager_KEY_AutoLoadProtocols			"AutoLoadProtocols"
 #define _NetworkManager_KEY_ListenChannels				"ListenChannels"
 #define _NetworkManager_KEY_StaticRoutes				"StaticRoutes"
 #define _NetworkManager_KEY_AutoConnect				"AutoConnect"

 #define _NetworkManager_EVENT_NetworkProtocolInstalled	"network_protocol_installed"


 #define _NetworkManager_METHOD_Hosts_retrieve			"retrieve_hosts"

 #define _NetworkManager_METHOD_Hosts_list				"list_hosts"
 #define _NetworkManager_METHOD_Channels_list			"list_connections"
 #define _NetworkManager_METHOD_Protocols_list			"list_protocols"
 #define _NetworkManager_METHOD_Neighbours_list			"list_neighbours"
 #define _NetworkManager_METHOD_RoutesStatic_list		"list_routes_static"
 #define _NetworkManager_METHOD_RoutesDynamic_list		"list_routes_dynamic"
 #define _NetworkManager_METHOD_NetworkTree_list		"list_network"

 #define _NetworkManager_METHOD_Stats_get				"get_stats"


 #define _NetworkManager_METHOD_CreateChannel			"create_channel"

 #define _NetworkManager_METHOD_Host_connect			"connect"
 #define _NetworkManager_METHOD_Host_disconnect			"disconnect"
 //#define _NetworkManager_METHOD_Host_reshare			"reshare"
 #define _NetworkManager_METHOD_Host_ping				"ping"

 
 #define _NetworkManager_METHOD_StatusSummary			"status"

 #define _NetworkManager_ERROR_autoconnect				2101

 #define _NetworkManager_ERROR_channel_error			4101
 #define _NetworkManager_ERROR_channel_listen			4111

 #define _NetworkManager_ERROR_protocol_load			6101
 #define _NetworkManager_ERROR_protocol_listen			6111


class Bus;
class BusManager;
class NetworkOutMessageHandler;
class NetworkInMessageHandler;
class NetworkManagerLooper;
class WoshKernel;

class NetworkManager :		public WoshModule,
							public virtual INetworkChannelListener,
							public virtual INetworkProtocolListener
 {
	WOSH_MODULE(wosh::NetworkManager)

	typedef MapT<long, NetworkChannel*> tLongNetworkChannelMap;
	typedef ListT<NetworkProtocol*> tNetworkProtocolList;
	typedef MapT<std::string,std::string> tStrStrMap;
	typedef MapT<std::string, WoshHost*> tStrWoshHostMap;


	protected:
		/**
		 * @brief  Default constructor. Call base constructor and initialize some properties and hosted methods.
		 *         Local host (WoshHost) is initialized.
		 * @param parent [in] WoshKernel singleton, passed to WoshModule constructor
		 * @note   Called by WoshKernel only. Static getter (gamma singleton) will return NULL until kernel is created.
		 */
		NetworkManager( const WoshKernel* parent = NULL );

		WRESULT onKernelInitializing();
		
		WRESULT onKernelInitialized();

		WRESULT onKernelStopped();

		friend class wosh::WoshKernel;

	public:
		/**
		 * @brief  Destructor. Channels, Protocols and Hosts datasets are destroyed.
		 */
		virtual ~NetworkManager();

//@}
/** @name Public methods (not for bundles, usually hidden to most classes)
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief  Update information of a WOSH Host (local-host or remote).
		 * @param [in] host the source WoshHost object
		 * @note   used by Discovery service (as services::DiscoveryUdp)
		 */
		WRESULT updateWoshHost( const WoshHost* host );//will copy to local obj

		/**
		 * @brief  Get a copy of local-host object.
		 * @return copy of the WoshHost object representing local-host (myself) 
		 * @note   used by Discovery service (as services::DiscoveryUdp)
		 */
		WoshHost* getLocalWoshHost();

		/**
		 * @brief  create a channel
		 * @param [in] protocol_string configuration line (something like TCP://192.168.0.2:9797)
		 * @return WRET_OK
		 */
		WRESULT createChannel( const std::string& protocol_string );

// to be reviewed
bool isHost( const std::string& wosh_hostname ) const;

WRESULT installProtocol( NetworkProtocol* channel_protocol );

NetworkProtocol* loadProtocol( const std::string& network_protocol, double version = 0.0 );


//@}
/** @name Message Events (incoming message)
 * @{
 ******************************************************************************/
	public:
		void busMessage( const Message& message, const Bus* source );
//@}
/** @name NetworkChannel Events
 * @{
 ******************************************************************************/
	public:
		void channel_incomingMessage( NetworkChannel* channel, Message* message );
		void channel_Connected( NetworkChannel* channel, const WoshHost& host_name );
		void channel_Disconnected( NetworkChannel* channel, const std::string& host_name );
		void channel_Error( NetworkChannel* channel, int error_id, std::string error_description );
//@}
/** @name NetworkProtocol Events
 * @{
 ******************************************************************************/
	public:
		void network_protocol_supported( const std::string& protocol_string, NetworkChannel* channel, NetworkProtocol* source );
		void network_protocol_new_channel( NetworkChannel* channel, short in_out, NetworkProtocol* source );
//@}
/** @name Internal Mehods and Events management
 * @{
 ******************************************************************************/
	protected:
//	friend class wosh::WoshHost;
		friend class wosh::NetworkChannel;
		friend class wosh::NetworkProtocol;
		friend class wosh::BusManager;

		static NetworkManager* getInstance();

	protected:
		friend class wosh::NetworkOutMessageHandler;
		friend class wosh::NetworkInMessageHandler;
		friend class wosh::NetworkManagerLooper;

static void push_to_BusManager( Message* message, NetworkChannel* channel);
static void push_message( const Message* message, const Bus* source );

	private:

// no mutex on Hosts
WRESULT _updateWoshHost_( const WoshHost* host, bool raise_event, bool never_connect, int hops = -2 );

WRESULT getChannelsOf_( std::vector<NetworkChannel*>& channels, WoshHost* host, bool only_connected );

WRESULT autoConnect_( const std::string& name, bool new_host );
NetworkProtocol* findBestProtocol_( WoshHost* host, std::vector<std::string>& protocolsAvailable );

WRESULT pingHost_( WoshHost* host, NetworkChannel* channel );

WRESULT removeHost_( WoshHost* host );
WRESULT removeChannel_( NetworkChannel* channel );

void busMessageHost_( const Message& message, WoshHost* host );

// void incomingMessage( NetworkChannel* channel, Message* message );

	private:
		Response* mmDoList( const Request* request );
		Response* mmDoListNeighbours( const Request* request );
		Response* mmDoListNetworkTree( const Request* request );
		Response* mmDoListRoutesStatic( const Request* request );
		Response* mmDoListRoutesDynamic( const Request* request );

		Response* mmDoGetStats( const Request* request );
		Response* mmDoCreateChannel( const Request* request );
		Response* mmDoStatusSummary( const Request* request );

	private:
		WoshHost* localHost;				///< also included in map-list 'Hosts', index=0
		tStrWoshHostMap Hosts;				///< all known hosts
		URI HostsVirtualURI;				///< base URI for hosts (:/Network/Hosts)
		int hostTimeout;					///< how long to keel a (lost) host alive
		short HostsAutoConnect;				///< auto-connect new hosts (flag)

		tNetworkProtocolList Protocols;		///< whose handles protocols
		URI ProtocolsVirtualURI;			///< base URI for protocols (:/Network/Protocols)

		tLongNetworkChannelMap Channels;	///< (active) channels
		URI ChannelsVirtualURI;				///< base URI for vonnections (:/Network/Channels)

		tStrStrMap staticRoutes;			///< static routes of pairs [target-host,proxy-host]

		NetworkOutMessageHandler* outgoingMsgHandler;	///< is the bridge of outgoing messages
		NetworkInMessageHandler* incomingMsgHandler;	///< buffer queue for incoming messages
		NetworkManagerLooper* hostTimeOutLooper;		///< loops hosts to remove ones out of date


}; // class def

}; // namespace wosh

#endif //__WOSH_Core_NetworkManager_H__
